package Entity;

import Util.Constants.*;

import java.util.EnumMap;

/**
 * 此类是用于表示图中节点的数据结构。
 * 每个迷宫是一组连通的节点，每个节点都有对应于枚举移动的相邻节点。
 * 每个节点存储检查和更新游戏当前状态所需的所有信息。
 */
public class Node {
    public final int x, y, nodeIndex, pillIndex, powerPillIndex, numNeighbouringNodes;
    public final EnumMap<MOVE, Integer> neighbourhood = new EnumMap<MOVE, Integer>(MOVE.class);
    public EnumMap<MOVE, MOVE[]> allPossibleMoves = new EnumMap<MOVE, MOVE[]>(MOVE.class);
    public EnumMap<MOVE, int[]> allNeighbouringNodes = new EnumMap<MOVE, int[]>(MOVE.class); //所有相邻节点
    public EnumMap<MOVE, EnumMap<MOVE, Integer>> allNeighbourhoods = new EnumMap<MOVE, EnumMap<MOVE, Integer>>(MOVE.class);

    /*
     * 实例化一个新的Node.
     */
    public Node(int nodeIndex, int x, int y, int pillIndex, int powerPillIndex, int[] _neighbourhood) {
        this.nodeIndex = nodeIndex;
        this.x = x;
        this.y = y;
        this.pillIndex = pillIndex;
        this.powerPillIndex = powerPillIndex;

        MOVE[] moves = MOVE.values();
        for (int i = 0; i < _neighbourhood.length; i++) {
            if (_neighbourhood[i] != -1) {
                neighbourhood.put(moves[i], _neighbourhood[i]);
            }
        }
        numNeighbouringNodes = neighbourhood.size();

        for (int i = 0; i < moves.length; i++) {
            if (neighbourhood.containsKey(moves[i])) {
                EnumMap<MOVE, Integer> tmp = new EnumMap<MOVE, Integer>(neighbourhood);
                tmp.remove(moves[i]);
                allNeighbourhoods.put(moves[i].opposite(), tmp);
            }
        }

        allNeighbourhoods.put(MOVE.NEUTRAL, neighbourhood);

        int[] neighbouringNodes = new int[numNeighbouringNodes];
        MOVE[] possibleMoves = new MOVE[numNeighbouringNodes];

        int index = 0;

        for (int i = 0; i < moves.length; i++) {
            if (neighbourhood.containsKey(moves[i])) {
                neighbouringNodes[index] = neighbourhood.get(moves[i]);
                possibleMoves[index] = moves[i];
                index++;
            }
        }

        for (int i = 0; i < moves.length; i++)//check all moves
        {
            if (neighbourhood.containsKey(moves[i].opposite()))//move is part of neighbourhood
            {
                int[] tmpNeighbouringNodes = new int[numNeighbouringNodes - 1];
                MOVE[] tmpPossibleMoves = new MOVE[numNeighbouringNodes - 1];

                index = 0;

                for (int j = 0; j < moves.length; j++)//add all moves to neighbourhood except the one above
                {
                    if (moves[j] != moves[i].opposite() && neighbourhood.containsKey(moves[j])) {
                        tmpNeighbouringNodes[index] = neighbourhood.get(moves[j]);
                        tmpPossibleMoves[index] = moves[j];
                        index++;
                    }
                }

                allNeighbouringNodes.put(moves[i], tmpNeighbouringNodes);
                allPossibleMoves.put(moves[i], tmpPossibleMoves);
            }
        }

        allNeighbouringNodes.put(MOVE.NEUTRAL, neighbouringNodes);
        allPossibleMoves.put(MOVE.NEUTRAL, possibleMoves);

    }
}
